<?php

namespace Managers;

class Pages extends BaseManager implements CrudManager
{
    const TABLE = '\Catalog\Pages';
    protected $__table = self::TABLE;
    protected $cacheNames = array('menu');

    const TIME_IN_CACHE = 600; // 10 minutes

    const DEFAULT_SORT_ORDER = 10;

    protected function createQueryBuilder()
    {
        $qb = $this->_em->createQueryBuilder()
            ->select('partial p.{id,title}, pa')
            ->from($this->__table, 'p')
            ->leftJoin('p.parent', 'pa')
            ->andWhere('p.isDel = 0');
        return $qb;
    }

    public function getMenu()
    {
        $cacheName = $this->cacheNames[0];
        $res = $this->_getCacheManager()->load($cacheName);
        if (!$res) {
            $res = $this->getTreeList();
            $this->_getCacheManager()->save($res, $cacheName, array(), self::TIME_IN_CACHE);
        }
        return $res;
    }

    public function getTreeList()
    {
        $qb = $this->createQueryBuilder()
            ->andWhere('p.parent is null');
        $res = $qb->getQuery()->getArrayResult();
        $res = $this->addChildren($res);
        return $res;
    }

    public function addChildren(array $pages)
    {
        if (!count($pages)) {
            return $pages;
        }
        $qb = $this->createQueryBuilder();
        $commentsIds = Utils::rebuildArray($pages);
        $qb->andWhere($qb->expr()->in('p.parent', $commentsIds));
        $children = $qb->getQuery()->getArrayResult();
        if (count($children)) {
            $children = $this->addChildren($children);
        }
        foreach ($pages as &$page) {
            $page['children'] = array();
            foreach ($children as $child) {
                if ($child['parent']['id'] == $page['id']) {
                    $page['children'][] = $child;
                }
            }
        }

        return $pages;
    }

    public function create(array $values)
    {
        $entity = new \Catalog\Pages();
        $entity->setSortOrder(self::DEFAULT_SORT_ORDER);
        $entity->setIsDel(false);
        $this->setEntityValues($entity, $values);
        if ($values['parent']) {
            $parentRef = $this->_em->getReference($this->__table, $values['parent']);
            $entity->setParent($parentRef);
        }
        $this->_em->persist($entity);
        $this->flush();
        return $entity;
    }

    public function update(array $values)
    {
        $entity = $this->find($values['id']);
        $this->setEntityValues($entity, $values);
        $this->_em->persist($entity);
        $this->flush();
        return $entity;
    }

    private function setEntityValues(\Catalog\Pages $entity, $values)
    {
        $entity->setContent($values['content']);
        $entity->setTitle($values['title']);
    }

    public function dnd(\Zend_Controller_Request_Abstract $request)
    {
        $operation = $request->getParam('operation');
        $id = $request->getParam('id');
        $ref = $request->getParam('ref');
        switch ($operation) {
            case 'move_node':
                $result = $this->move($id, $ref);
                break;
            case 'remove_node':
                $result = $this->delete($id);
                break;
            case 'rename_node':
                $result = $this->rename($id, $request->getParam('title'));
                break;
            default:
                $result = false;
        }
        return $result;
    }

    public function move($mainId, $parentId)
    {
        $mainEntity = $this->find($mainId);
        /* @var \Catalog\Pages $mainEntity */
        if (!$mainEntity) {
            return false;
        }
        if ($parentId) {
            $parentEntity = $this->_em->getReference($this->__table, $parentId);
            $mainEntity->setParent($parentEntity);
        } else {
            $mainEntity->setParent(null);
        }

        $this->_em->persist($mainEntity);
        $this->flush();
        return true;
    }

    public function rename($id, $name)
    {
        $entity = $this->find($id);
        /* @var \Catalog\Pages $entity */
        if (!$entity) {
            return false;
        }

        $entity->setTitle($name);
        $this->_em->persist($entity);
        $this->flush();
        return true;
    }

    /**
     * Возвращает елемент по ID, false - если елемент не найден.
     *
     * @param array|bool $id
     */
    public function getById($id)
    {
        $qb = $this->createQueryBuilder()
            ->select('p, pa')
            ->andWhere('p.id = :id')->setParameter('id', $id);
        $res = $qb->getQuery()->getArrayResult();

        return count($res) ? $res[0] : false;
    }
}
